package com.xiang.sql.service;

import java.util.List;

import org.springframework.stereotype.Service;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiang.api.Util;
import com.xiang.sql.StaticSql;
import com.xiang.sql.entity.Group;
import com.xiang.sql.entity.User;
import com.xiang.sql.mapper.UserMapper;

import jakarta.annotation.Resource;

/**
 * 用户 服务实现类
 * 
 * @author mac-xiang
 */
@Service
public class UserService extends ServiceImpl<UserMapper, User> {
  @Resource
  UserMapper mapper;

  public User refreshToken(User user) {
    user.token = Util.getUUID();
    mapper.update(new UpdateWrapper<User>().set("token", user.token).eq("id", user.id));
    return user;
  }

  public User getToken(User user, long timeOut) {
    if (user != null) {
      // if (timeOut < 0l) {
      // timeOut = 600l;
      // }
      // if (timeOut == 0l) {
      // timeOut -= Util.time();
      // } else {
      // timeOut += Util.time();
      // }
      // JSONObject t = new JSONObject();
      // t.put("timeOut", timeOut);
      // t.put("id", user.getId());
      // t.put("key", IdWorker.getId());
      // t.put("password", user.getPassword());
      // return AES.encrypt(t.toJSONString(), config.login.key);
      // user.token = Util.getUUID();
      // mapper.update(null, new
      // UpdateWrapper<User>()
      // .set("token", user.token).eq("id", user.id));
      if (Util.isEmpty(user.token)) {
        refreshToken(user);
      }
      user.gLive();
      return user;
    }
    throw new RuntimeException("用户不存在");
  }

  public User getToken(User user) {
    return getToken(user, 0l);
  }

  public User getToken(Long id) {
    if (id != null) {
      return getToken(mapper.selectById(id));
    }
    throw new RuntimeException("用户id不存在");
  }

  public User getToken(JSONObject p) {
    try {
      QueryWrapper<User> wrapper = new QueryWrapper<>();
      wrapper.eq("username", p.getString("username"))
          .eq("password", Util.toHash(p.getString("password"), false))
          .eq("state", 0).last("limit 1");
      return getToken(mapper.selectOne(wrapper));
    } catch (Exception e) {
      throw new RuntimeException(Util.errString(e));
    }
    // throw new RuntimeException("用户名或密码错误");
  }

  public User getTokenByWxid(String wxid) {
    User user = null;
    try {
      user = mapper.selectOne(new QueryWrapper<User>().eq("wxid", wxid));
    } catch (Exception e) {
    }
    if (user == null) {
      JSONObject p = new JSONObject();
      p.put("wxid", wxid);
      p.put("gid", "2");
      user = this.create(p, null);
    }
    return this.getToken(user);
  }

  private QueryWrapper<User> readWrapper(JSONObject p, User per) {
    QueryWrapper<User> ret = Util.getQuery(p, User.class);
    if (per == null || !per.per("用户查询")) {
      ret.select("id, `pid`, `permission`, `name`");
    }
    return ret;
  }

  public List<User> getList(JSONObject p, User per) {
    return mapper.selectList(readWrapper(p, per));
  }

  public Page<User> getPage(Page<User> page, JSONObject p, User per) {
    return mapper.selectPage(page == null ? new Page<User>(1, 100) : page, readWrapper(p, per));
  }

  public Page<User> getPage(JSONObject p, User per) {
    return getPage(null, p, per);
  }

  public User create(JSONObject p, User per) {
    try {
      User entity = Util.getEntity(p, User.class);
      byte[] permission = new byte[20];
      if (per == null || !per.per("用户创建")) {
        entity.permission = new byte[20];
        permission[0] = 1;
        entity.commission = 10;
      } else {
        permission = per.permission;
      }

      entity.createValidator();
      entity.password = Util.toHash(entity.password, false);
      for (int i = 0; i < permission.length; i++) {
        entity.permission[i] &= permission[i];
      }
      entity.permission[0] |= 1;
      mapper.insert(entity);
      return entity;
    } catch (Exception e) {
      throw new RuntimeException(Util.errString(e));
    }
  }

  public int update(JSONObject p, User per) {
    try {
      QueryWrapper<User> qw = Util.getQuery(p, User.class);
      if (per != null && !per.per("用户修改")) {
        if (per.id.equals(p.getString("id"))) {
          int r = 0;
          if (p.containsKey("name")) {
            r += change_name(p, per);
          }
          if (p.containsKey("username")) {
            r += change_username(p, per);
          }
          if (p.containsKey("password")) {
            r += change_password(p, per);
          }
          if (p.containsKey("other")) {
            r += mapper
                .update(new UpdateWrapper<User>().eq("id", p.getString("id")).set("`other`", p.getString("other")));
          }

          return r;
        }
        throw new RuntimeException("没有权限");
      }
      User entity = Util.getEntity(p, User.class);
      if (entity.password != null) {
        entity.password = Util.toHash(entity.password, false);
      }
      return mapper.update(entity, qw);
    } catch (Exception e) {
      throw new RuntimeException(Util.errString(e));
    }
  }

  public Object read(JSONObject p, User per) {
    Page<User> page = Util.getPage(p, User.class);
    return page == null ? getList(p, per) : getPage(page, p, per);
  }

  public int delete(JSONObject p, User per) {
    try {
      if (per != null && per.per("用户删除")) {
        QueryWrapper<User> q = new QueryWrapper<>();
        String id = p.getString("id");
        if (id != null) {
          q.eq("id", id);
        }

        return mapper.delete(q);
      }
      throw new RuntimeException("没有权限");
    } catch (Exception e) {
      throw new RuntimeException(Util.errString(e));
    }
  }

  public long count(JSONObject p, User per) {
    return this.count(readWrapper(p, per));
  }

  public User getByToken(String tokenString) {
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.eq("token", tokenString).eq("state", 0).last("limit 1");
    User ret = mapper.selectOne(wrapper);
    if (ret != null) {
      String[] b = { "0", "1", "2" };
      if (Util.includes(b, ret.id) < 0 && Util.includes(b, ret.gid) < 0
          && Util.includes(b, StaticSql.service.group.pid(ret.gid)) < 0) {
        ret.gid = "2";
        mapper.update(new UpdateWrapper<User>().eq("id", ret.id).set("gid", 2));
      }
      return this.getToken(ret);
    }
    throw new RuntimeException("账户未登录:" + tokenString);
  }

  public int change_username(JSONObject p, User per) {
    String id = p.getString("id"), n = p.getString("username");
    if (n != null && id != null && (per.per("修改用户名") || per.id.equals(id))) {
      if (count(new QueryWrapper<User>().eq("username", n)) > 0) {
        throw new RuntimeException("提交的用户名重复");
      }
      return mapper.update(new UpdateWrapper<User>().eq("id", id).set("`username`", n));
    }
    throw new RuntimeException("没有权限");
  }

  public int change_password(JSONObject p, User per) {
    String id = p.getString("id"), n = p.getString("password");
    if (n != null && id != null && (per.per("修改密码") || per.id.equals(id))) {
      return mapper.update(new UpdateWrapper<User>().eq("id", id).set("`password`",
          Util.toHash(n, false)));
    }
    throw new RuntimeException("没有权限");
  }

  public int change_name(JSONObject p, User per) {
    String id = p.getString("id"), n = p.getString("name");
    if (n != null && id != null && (per.per("修改昵称") || per.id.equals(id))) {
      return mapper.update(new UpdateWrapper<User>().eq("id", id).set("`name`", n));
    }
    throw new RuntimeException("没有权限");
  }

  public int change_commission(JSONObject p, User per) {
    String id = p.getString("id"), n = p.getString("commission");
    if (n != null && id != null && per.per("修改用户抽成")) {
      return mapper.update(new UpdateWrapper<User>().eq("id", id).set("`commission`", n));
    }
    throw new RuntimeException("没有权限");
  }

  public int change_gid(JSONObject p, User per) {
    String id = p.getString("id"), n = p.getString("gid");
    boolean merch = p.getBooleanValue("merch");
    if (id != null) {
      if (merch && !Util.isEmpty(n) && per.per("转化为商家")) {
        StaticSql.mapper.group.update(new UpdateWrapper<Group>().eq("id", n).set("`create`", id));
        return mapper.update(new UpdateWrapper<User>().eq("id", id).set("`gid`", n));
      } else if (!merch && per.per("转为消费者")) {
        StaticSql.mapper.group.update(new UpdateWrapper<Group>().eq("`create`", id).set("`create`", ""));
        return mapper.update(new UpdateWrapper<User>().eq("id", id).set("`gid`", "2"));
      }
    }
    throw new RuntimeException("没有权限");
  }

  public String getWxidById(String id) {
    if (id != null) {
      User u = mapper.selectOne(new QueryWrapper<User>().eq("id", id).select("id,`wxid`"));
      if (u != null) {
        return u.wxid;
      }
    }
    return null;
  }

  public User getParentById(String id) {
    return mapper.getParentById(id);
  }

  public void setPid(JSONObject p, User per) {
    String pid = p.getString("pid");
    Group g = null;
    if (!Util.isEmpty(pid)
        && Util.isEmpty(per.pid)
        && !StaticSql.service.group.isMerchant(per.gid)
        && (g = StaticSql.service.group.getById(pid)) != null) {
      mapper.update(new UpdateWrapper<User>().eq("id", per.id).set("pid", g.create));
    }
  }

  public User me(JSONObject p, User per) {
    return per;
  }

  public Object login(JSONObject p, User per) {
    User u = this.getToken(p);
    if (u != null) {
      if (p.getBooleanValue("del") && !u.id.equals(per.id)) {
        mapper.deleteById(per.id);
      }
      mapper.update(new UpdateWrapper<User>().eq("id", per.id).set("wxid", ""));
      mapper.update(new UpdateWrapper<User>().eq("id", u.id).set("wxid", per.wxid));
      return u;
    }
    return null;
  }

  public int getLive(String id) {
    List<String> ids = new java.util.ArrayList<>();
    while (id != null) {
      if (ids.contains(id)) {
        ids.add(id);
        break;
      }
      ids.add(id);
      id = mapper.getPidById(id);
    }
    int ret = ids.size();
    if (ret > 0) {
      if (!ids.get(--ret).equals("") && ret > 0) {
        StaticSql.run.query(String.format("UPDATE `user` SET `pid` = '' WHERE `user`.`id` = '%s';", ids.get(ret - 1)));
      }
    }
    return ret;
  }
}
